package auth

import (
	"fmt"
	"github.com/golang-jwt/jwt"
	"time"
)

type ExpirableClaims struct {
	ExpiresAt int64 `json:"exp,omitempty"`
}

type AccessTokenClaims struct {
	ExpirableClaims
	Account  string      `json:"sub"`
	UserId   interface{} `json:"uid"`
	Audience string      `json:"aud,omitempty"`
	Issuer   string      `json:"iss,omitempty"`
	Accesses []Access    `json:"accesses,omitempty"`
}

func newAccessTokenClaims(user User, accesses []Access) *AccessTokenClaims {
	return &AccessTokenClaims{
		Account:  user.Account(),
		UserId:   user.Id(),
		Audience: "", //TODO
		Issuer:   "", //TODO
		ExpirableClaims: ExpirableClaims{
			ExpiresAt: time.Now().Add(config.maxAccessTokenAge).Unix(),
		},
		Accesses: accesses,
	}
}

type RefreshTokenClaims struct {
	ExpirableClaims
	UserId  interface{} `json:"uid"`
	Account string      `json:"sub"`
}

func newRefreshTokenClaims(user User) *RefreshTokenClaims {
	return &RefreshTokenClaims{
		UserId:  user.Id(),
		Account: user.Account(),
		ExpirableClaims: ExpirableClaims{
			ExpiresAt: time.Now().Add(config.maxRefreshTokenAge).Unix(),
		},
	}
}

func (t *ExpirableClaims) Valid() error {

	vErr := new(jwt.ValidationError)
	now := time.Now().Unix()

	// The claims below are optional, by default, so if they are set to the
	// default value in Go, let's not fail the verification for them.
	if !t.VerifyExpiresAt(now) {
		delta := time.Unix(now, 0).Sub(time.Unix(t.ExpiresAt, 0))
		vErr.Inner = fmt.Errorf("token is expired by %v", delta)
		vErr.Errors |= jwt.ValidationErrorExpired
	}

	if vErr.Errors == 0 {
		return nil
	}

	return vErr
}

func (t *ExpirableClaims) VerifyExpiresAt(cmp int64) bool {
	return t.ExpiresAt >= cmp
}

//TODO load public key when it updated
